/**
 * @file         jtc_msg_808_ec2_msg.h
 * @brief        Ec2的消息定义
 * @note    
 * @author       Akee
 * @date         2019-12-22
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2019-12-22  <td>1.0                   <td>Akee            <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */
#ifndef _JTC_MSG_808_EC2_MSG_H_
#define _JTC_MSG_808_EC2_MSG_H_

#include "ofc/ofc_types.h"
#include "ofc/ofc_object.h"
#include "mfc/mfc_string.h"
#include "jtmsg808/jtc_msg_808_2013.h"
#include "mfc/mfc_mem_codec.h"

#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 1)

/**
 * 终端通用应答(0x0900->0xFFD2)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2GenRespTag TJtMsg808Ec2GenResp;
struct TJtMsg808Ec2GenRespTag
{
    Word proto_num;
    QWord task_id;
    Byte result;
};
Bool JtMsg808Ec2GenRespEncode(TJtMsg808Ec2GenResp *msg, TMfMemCodec *codec);

/**
 * 传输任务描述协议(0x8900 -> 0xFF3B)
 */
typedef struct TJtMsg808Ec2FileTaskDescTag TJtMsg808Ec2FileTaskDesc;
struct TJtMsg808Ec2FileTaskDescTag
{
    Word ec2_msg_id;                  ///< ec2消息id
    QWord task_id;                    ///< 任务流水号 | 任务流水号
    Word code;                        ///< 消息码 | 传输任务的协议编码（网关下的任务中的协议码）
    Byte svr_file[160];               ///< 服务器上的文件名 | 在服务器上的文件名
    DWord file_size;                  ///< 文件尺寸 | 文件的size
    DWord crc;                        ///< CRC32 | 文件CRC32校验码
    DWord param1;                     ///< 参数1 | 目前仅用于标识同一任务的不同回传图片？？？
    DWord param2;                     ///< 参数2 | 目前仅用于标识同一任务的不同回传图片？？？
    //    Byte ext_param[];                  扩展参数 | 扩展参数，目前保留
};

/**
 * 传输任务异常应答原因枚举(0x8900 -> 0xFF3C)
 */
enum TJtMsg808Ec2TaskExceptReasonEnumTag
{
    kJtMsg808Ec2TaskExceptReasonFileNotExists   = 0,    ///< 文件不存在
    kJtMsg808Ec2TaskExceptReasonBusy            = 1,    ///< 终端忙
    kJtMsg808Ec2TaskExceptReasonTooLarge        = 2,    ///< 文件太大
    kJtMsg808Ec2TaskExceptReasonUnsupport       = 3,    ///< 终端不支持
    kJtMsg808Ec2TaskExceptReasonInvalidTask     = 4,    ///< 任务无效，可能是协议错误
    kJtMsg808Ec2TaskExceptReasonTaskExists      = 5,    ///< 任务已经存在，重复的任务
};
typedef enum TJtMsg808Ec2TaskExceptReasonEnumTag TJtMsg808Ec2TaskExceptReasonEnum;

/**
 * TJtMsg808Ec2GetDownloadData 请求下载一包数据协议(0x8900->0xFF45)
 */
typedef struct TJtMsg808Ec2GetDownloadDataTag TJtMsg808Ec2GetDownloadData;
struct TJtMsg808Ec2GetDownloadDataTag
{
    Word ec2_msg_id;        ///< Ec2消息Id
    QWord task_id;          ///< 任务流水号
    DWord pos;              ///< 请求读取位置 | 终端请求读取的数据在文件中的位置
    DWord size;             ///< 请求读取长度 | 请求读取数据的长度。
};

/**
 * 传输任务异常应答协议(0x8900 -> 0xFF3C)
 */
typedef struct TJtMsg808Ec2TaskExceptRespTag TJtMsg808Ec2TaskExceptResp;
struct TJtMsg808Ec2TaskExceptRespTag
{
    Word ec2_msg_id;                  ///< ec2消息id
    QWord task_id;                    ///< 任务流水号 | 任务流水号
    Byte reason;                      ///< 异常原因,参考TJtMsg808Ec2TaskExceptReasonEnum
};

#pragma pack(pop)

/**
 * 网关向终端发送传输任务确认包->执行结果类型(0x8900->0xFF3D)
 */
enum TJtMsg808Ec2TaskFonfirmResultEnumTag
{
    kJtMsg808Ec2TaskFonfirmResultOk,            ///< 消息已收到
    kJtMsg808Ec2TaskFonfirmResultResend,        ///< 重传当前包
    kJtMsg808Ec2TaskFonfirmResultCancel,        ///< 取消当前任务
    kJtMsg808Ec2TaskFonfirmResultRestart,       ///< 重新开始传输
    kJtMsg808Ec2TaskFonfirmResultDescRequest,   ///< 要求重新发送任务描述
    kJtMsg808Ec2TaskFonfirmResultCrcError       ///< 错误的Crc校验
};
typedef enum TJtMsg808Ec2TaskFonfirmResultEnumTag TJtMsg808Ec2TaskFonfirmResultEnum;

#pragma pack(push, 1)
/**
 * TJtMsg808Ec2FileTaskConfirm 网关向终端发送传输任务确认包(0x8900->0xFF3D)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2FileTaskConfirmTag TJtMsg808Ec2FileTaskConfirm;
struct TJtMsg808Ec2FileTaskConfirmTag
{
    Word ec2_msg_id;        ///< Ec2消息Id
    QWord task_id;          ///< 任务ID | 任务ID
    Byte result;            ///< 执行结果类型，参考TJtMsg808Ec2TaskFonfirmResultEnum

    /// 参数 | 下一个数据包的任务的位置（已经收到：下一包位置；重传：重传的位置 取消任务：null 重新开始传输：重传位置4：null 5：null）
    DWord param;
};
#pragma pack(pop)

/**
 * 网关向终端发送传输任务确认包解码(0x8900->FF3D)
 * @param self: 对象指针
 * @param buf: 需要解码的内容
 * @param buf_size: 解码的内容大小
 * @return True: 解码成功; False: 解码失败
 */
Bool JtMsg808Ec2FileTaskConfirmDecode(TJtMsg808Ec2FileTaskConfirm *msg, Byte *buf, Int32 buf_size);

#pragma pack(push, 1)
/**
 * TJtMsg808Ec2FileUpdateTask 终端更新任务协议(0x8900->FF3A)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2FileUpdateTaskTag TJtMsg808Ec2FileUpdateTask;
struct TJtMsg808Ec2FileUpdateTaskTag
{
    Word ec2_msg_id;        ///< Ec2消息Id
    QWord task_id;          ///< 任务ID
    Byte svr_file[160];     ///< 文件在服务器路径。相对路径使用"#"，表示在服务器根路径\eid\对应终端号码路径下面
    Byte trm_file[64];      ///< 文件在终端路径
    DWord file_size;        ///< 文件的size
    DWord crc;              ///< 文件的crc编码
};
#pragma pack(pop)

/**
 * 终端更新任务协议解码(0x8900->FF3A)
 * @param msg: 解码后的消息内容
 * @param buf: 需要解码的内容
 * @param buf_size: 解码的内容大小
 * @return True: 解码成功; False: 解码失败
 */
Bool JtMsg808Ec2FileUpdateTaskDecode(TJtMsg808Ec2FileUpdateTask *msg, Byte *buf, Int32 buf_size);

/**
 * TJtMsg808Ec2DownloadData 网关向终端回应一包文件数据(0x8900->FF46)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2DownloadDataTag TJtMsg808Ec2DownloadData;
struct TJtMsg808Ec2DownloadDataTag
{
PROTECTED
    TOfObject parent_;
    TOfVirtualMethod Destroy_;

PUBLIC
    Word ec2_msg_id;
    QWord task_id;
    DWord pos;
    TMfString data;
};

void TJtMsg808Ec2DownloadDataCreate(TJtMsg808Ec2DownloadData *self);

Bool TJtMsg808Ec2DownloadDataDecode(TJtMsg808Ec2DownloadData *self, Byte *buf, Int32 buf_size);

/**
 * 终端发送任务完成消息结果枚举
 */
enum TJtMsg808Ec2TaskFinishResultEnumTag
{
    kJtMsg808Ec2TaskFinishOk        = 0,    ///< 执行完成
    kJtMsg808Ec2TaskFinishCrcError  = 1,    ///< crc编码校验错误
    kJtMsg808Ec2TaskFinishFail      = 2,    ///< 被传输的文件由于其他原因已经被修改，造成传输失败
};
typedef enum TJtMsg808Ec2TaskFinishResultEnumTag TJtMsg808Ec2TaskFinishResultEnum;

#pragma pack(push, 1)
/**
 * 终端发送任务完成消息(0x8900->0xFF41)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2TaskFinishTag TJtMsg808Ec2TaskFinish;
struct TJtMsg808Ec2TaskFinishTag
{
    Word ec2_msg_id;    ///< ec2消息id
    QWord task_id;      ///< 任务流水号 | 任务流水号
    Byte result;        ///< 完成结果,参考TJtMsg808Ec2TaskFinishResultEnum
};

/**
 * 终端发送任务完成消息(0x8900->0xFF37)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2FileUploadTaskTag TJtMsg808Ec2FileUploadTask;
struct TJtMsg808Ec2FileUploadTaskTag
{
    Word ec2_msg_id;    ///< ec2消息id
    QWord task_id;      ///< 任务流水号 | 任务流水号
    Byte svr_file[160]; ///< 文件在服务器路径。相对路径使用"#"，表示在服务器根路径\eid\对应终端号码路径下面
    Byte trm_file[64];  ///< 文件在终端路径
    Byte level;         ///< 任务等级 | 任务等级：0 最低级别传输，设备关机任务即结束，且不进行整个文件的CRC32校验（一般用于日志文件上传）1 中级传输，任务不会因关机而丢失，但整个文件校验失败或源文件发生变化不进行重传（一般用于重要日志获图片上传）2 除非任务被终止，否则一直会处理直到准确无误完成 3. 压缩上传
};
#pragma pack(pop)

/** 
 * 文件上传任务解码
 * @param msg: 解码后的消息
 * @param buf: 需要解码的消息数据
 * @param buf_size: 需要解码的消息长度
 * @return True: 解码成功: False: 解码失败
 */
Bool JtMsg808Ec2FileUploadTaskDecode(TJtMsg808Ec2FileUploadTask *msg, Byte *buf, Int32 buf_size);

#pragma pack(push, 1)
/**
 * 上传一包数据协议(0x8900->0xFF3E)
 */
typedef struct TJtMsg808Ec2FileUploadDataTag TJtMsg808Ec2FileUploadData;
struct TJtMsg808Ec2FileUploadDataTag
{
    Word ec2_msg_id;        ///< ec2消息id
    QWord task_id;          ///< 任务流水号
    DWord pos;              ///< 数据包位置 | 数据包在文件中的位置
    Byte content[1];        ///< 数据内容 |
};
#pragma pack(pop)


/**
 * 创建Ec2的消息
 * @param ec2_msg_id: ec2扩展消息id
 * @param msg_len: 消息长度
 * @param data: 消息指向的地址，仅当返回值不为NULL时有效
 * @return NULL: 无效; 其他: Ec2消息
 */
TJtMsg808UploadByPass *JtCreateMsg808UploadByPassEc2Msg(Word ec2_msg_id, Int32 msg_len, UInt8 **data);



/**
 * Http下载相关
 ******************************************************************************
 */
#pragma pack(push, 1)

/**
 * http下载任务下发(0x8900->0xAF30)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpDownloadTaskTag TJtMTJtMsg808Ec2HttpDownloadTask;
struct TJtMsg808Ec2HttpDownloadTaskTag
{
    QWord task_id;          ///< 任务序列号 | 对应的平台消息的任务序列号
    DWord file_size;        ///< 文件大小 | 文件大小长度
    Byte md5_value[32];     ///< 文件MD5值 | 文件MD5①值摘要：字符串长度为32位
    Byte upgrade_type;      ///< 升级方式 | 0:开机升级，1:立即升级 2:静默升级,@ref 参考TJtMsg808Ec2HttpUpgradeTypeEnum
    Byte upgrade_target;    ///< 升级类别(目标) | 0：终端
    Byte is_cancel;         ///< 是否取消 | 1:取消任务 其他：无效
    UInt8 htt_url_len;     ///< http下载地址长度| 不大于128
    Byte *http_url;         ///< http下载地址 | 包含域名和http字段
};

/** 
 * http下载任务下发解码
 * @param msg: 解码后的消息
 * @param buf: 需要解码的消息数据
 * @param buf_size: 需要解码的消息长度
 * @return True: 解码成功: False: 解码失败
 */
Bool JtMsg808Ec2HttpDownloadTaskDecode(TJtMTJtMsg808Ec2HttpDownloadTask *msg, TMfMemCodec *codec);

/**
 * http下载任务应答(0x8900->0x2F30)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpDownloadTaskRespTag TJtMsg808Ec2HttpDownloadTaskResp;
struct TJtMsg808Ec2HttpDownloadTaskRespTag
{
    QWord task_id;          ///< 任务序列号 | 任务ID
    Byte resp_result;       ///< 应答结果 | 参考
    DWord error;            ///< 鸿泉错误码 | 平台只需展示数字
};

/** 
 * 文件上传任务编码
 * @param msg: 需要编码的的消息
 * @param buf: 编码的消息缓冲区
 * @param buf_size: 需要编码的缓冲区长度
 * @return True: 解码成功: False: 解码失败
 */
Bool JtMsg808Ec2HttpDownloadTaskRespEncode(TJtMsg808Ec2HttpDownloadTaskResp *msg, TMfMemCodec *codec);

/**
 * http下载任务状态上报(0x0900->0x2F31)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpStateReportTag TJtMsg808Ec2HttpStateReport;
struct TJtMsg808Ec2HttpStateReportTag
{
    QWord task_id;          ///< 任务序列号 | 对应的平台消息的任务序列号
    Byte state;             ///< 状态 | @ref 参考 TJtMsg808Ec2HttpStateEnum
    DWord progress_error;   ///< 错误码或进度 | 下载中状态上报进度，单位%， 校验成功、升级成功状态错误码为0， 下载失败、校验失败、升级失败上报错误码，平台只需展示数字
    Byte ver_len;           ///< 当前版本长度 | 版本长度
    Byte *ver;              ///< 当前版本 | 平台只需展示
};

/** 
 * http下载任务状态上报编码
 * @param msg: 需要编码的的消息
 * @param buf: 编码的消息缓冲区
 * @param buf_size: 需要编码的缓冲区长度
 * @return True: 编码成功: False: 编码失败
 */
Bool JtMsg808Ec2HttpStateReportEncode(TJtMsg808Ec2HttpStateReport *msg, TMfMemCodec *codec);

/**
 * http下载任务状态上报应答(0x8900->0xAF31)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpStateReportRespTag TJtMsg808Ec2HttpStateReportResp;
struct TJtMsg808Ec2HttpStateReportRespTag
{
    QWord task_id;          ///< 任务序列号 | 对应的平台消息的任务序列号
    Byte resp_result;       ///< 应答结果 | @ref 参考TJtMsg808Ec2HttpStateRespResultEnum
};

/** 
 * http下载任务状态上报应答解码
 * @param msg: 解码后的消息
 * @param buf: 需要解码的消息数据
 * @param buf_size: 需要解码的消息长度
 * @return True: 解码成功: False: 解码失败
 */
Bool JtMsg808Ec2HttpStateReportRespDecode(TJtMsg808Ec2HttpStateReportResp *msg, TMfMemCodec *codec);


#pragma pack(pop)

#pragma pack(push, 1)


/**
 * 远程维护->shell命令下发(0x8900->0xF150)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2ShellCmdTaskTag TJtMsg808Ec2ShellCmdTask;
struct TJtMsg808Ec2ShellCmdTaskTag
{
    QWord task_id;    ///< 任务序列号 | 对应的平台消息的任务序列号
    Byte param_cnt;   ///< 参数个数
    Byte param_len;   ///< 参数长度
    Byte*  param;     ///< 参数
};

/** 
 * shell命令下发解码
 * @param msg: 解码后的消息
 * @param codec: 解码缓冲对象指针
 * @return True: 解码成功: False: 解码失败
 */
Bool JtMsg808Ec2ShellCmdTaskDecode(TJtMsg808Ec2ShellCmdTask *msg, Byte *buf, Int16 buf_size);

/**
 * 远程维护->shell命令下发(0x8900->0x0150)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2ShellCmdTaskRespTag TJtMsg808Ec2ShellCmdTaskResp;
struct TJtMsg808Ec2ShellCmdTaskRespTag
{
    QWord task_id;  ///< 任务序列号 | 对应的平台消息的任务序列号
    Word data_len;  ///< 数据长度
    Byte* data;    ///< shell执行结果
};

Bool JtMsg808Ec2ShellCmdTaskRespEncode(TJtMsg808Ec2ShellCmdTaskResp *msg, TMfMemCodec *codec);
#pragma pack(pop)

/**
 * 远程维护->文件传输相关
 ******************************************************************************
 */
#pragma pack(push, 1)

/**
 * 远程维护->文件下载，终端从平台下载
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpFileDownTaskTag TJtMsg808Ec2HttpFileDownTask;
struct TJtMsg808Ec2HttpFileDownTaskTag
{
    QWord task_id;          ///< 任务序列号 | 对应的平台消息的任务序列号
    DWord file_size;        ///< 文件大小 | 文件大小长度
    Byte md5_value[32];     ///< 文件MD5值 | 文件MD5值摘要：字符串长度为32位
    Byte is_cancel;         ///< 是否取消 | 1:取消任务 其他：无效
    Byte htt_url_len;       ///< http下载地址长度| 不大于255
    Byte *http_url;         ///< http下载地址 | 包含域名和http字段
    Byte path_len;          ///< 文件存放位置长度 | 不大于255
    Byte* path;             ///< 文件存放位置 | 全路径，包括文件名
};

Bool JtMsg808Ec2HttpFileDownTaskDecode(TJtMsg808Ec2HttpFileDownTask *msg, TMfMemCodec *codec);

/**
 * 远程维护->文件下载应答
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpFileDownTaskRespTag TJtMsg808Ec2HttpFileDownTaskResp;
struct TJtMsg808Ec2HttpFileDownTaskRespTag
{
    QWord task_id;          ///< 任务序列号 | 任务ID
    Byte resp_result;       ///< 应答结果 | 参考
    DWord error;            ///< 鸿泉错误码 | 平台只需展示数字
};

Bool JtMsg808Ec2HttpFileDownTaskRespEncode(TJtMsg808Ec2HttpFileDownTaskResp *msg, TMfMemCodec *codec);


/**
 * 远程维护->文件上传请求
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2HttpFileUpTaskTag TJtMsg808Ec2HttpFileUpTask;
struct TJtMsg808Ec2HttpFileUpTaskTag
{
    QWord task_id;          ///< 任务序列号 | 任务ID
    Word start_pos;         ///< 文件起始位置
    Word up_size;           ///< 请求上传大小
    Byte fname_len;         ///< 请求文件名长度
    Byte fname[80];         ///< 请求文件名
    Byte http_len;          ///< http接口长度
    Byte *http_url;         ///< http的url地址

};

Bool JtMsg808Ec2HttpFileUpTaskDecode(TJtMsg808Ec2HttpFileUpTask *msg, TMfMemCodec *codec);


typedef struct TJtMsg808Ec2HttpFileUpTaskRespTag TJtMsg808Ec2HttpFileUpTaskResp;
struct TJtMsg808Ec2HttpFileUpTaskRespTag
{
    QWord task_id;          ///< 任务序列号 | 任务ID
    Byte resp_result;       ///< 应答结果 | 参考
    DWord error;            ///< 鸿泉错误码 | 平台只需展示数字

};

Bool JtMsg808Ec2HttpFileUpTaskRespEncode(TJtMsg808Ec2HttpFileUpTaskResp *msg, TMfMemCodec *codec);

#pragma pack(pop)

#pragma pack(push, 1)

/**
 * 终端日志信息上报(0x0900->0xFF0F)
 ******************************************************************************
 */
typedef struct TJtMsg808Ec2TerminalLogReportTag TJtMsg808Ec2TerminalLogReport;
struct TJtMsg808Ec2TerminalLogReportTag
{
    Word log_content_len;  ///< 日志内容长度
    Byte *log_content;     ///< 日志内容
};

/**
 * 终端日志信息上报编码
 * @param msg: 需要编码的的消息
 * @param codec: : 编码缓冲对象指针
 * @return True: 编码成功: False: 编码失败
 */
Bool JtMsg808Ec2TerminalLogReportEncode(TJtMsg808Ec2TerminalLogReport *msg, TMfMemCodec *codec);

#pragma pack(pop)

#ifdef __cplusplus
} // extern "C" {
#endif
#endif
